--[[
Config Starts here
-]]
Server = "irc.rmrk.net" -- Where do you want to connect
Port = 6667 -- which port
Chan = "#thc" --Channel the bot should lurk in
Nicservpass = "sudafed" --nickserv pass Please register the nickname by yourself i refuse to automate this process.
Nick = "THC_TheHole"--The Nickname you want to give the bot eg. ahrefBot
User = "THC_TheHole beans beans2:Not a bot!" --I never got the hang of this just enter something along the lines of what i have

--[[
Config Ends here
#EDIT BELOW THIS LINE AT YOUR OWN PERIL!
-]]

--Internal Variables here Please do not edit them
Ops = {}
Players = 0
Host = GetConVarString("hostname")
Map = string.Replace(game.GetMap(),".bsp","")
--Hooks are placed at the bottom so i can singleplayer ignore them at will. 	
require("socket")
--types = { "props","sents"}
function ircSend(txt)
	if not s then return end
	send = s:send(txt.."\r\n")
	if not send then
		print("ERROR Sending: "..txt)
	end
end

function ircMsg(txt)
	ircSend("PRIVMSG "..Chan.." :"..txt)
end

function ircStart()
	if s then
		s:close()
	end
	s = socket.connect(Server, Port)
	print(s)
	s:settimeout(0)
	s:setoption("keepalive",true)
	ircSend("NICK "..Nick)
	ircSend("USER "..User)
	timer.Simple(2,function()
		ircSend("PRIVMSG nickserv :IDENTIFY "..Nicservpass)	
		ircSend("JOIN "..Chan) 
	end)  
	timer.Simple(4,function() 
		ircSend("PRIVMSG "..Chan.." :I HAVE ARRIVED") 
		changeTopic()
	end)
	
end
--old initialize hook here

function ircShut()
    ircSend("QUIT OMG I Think The Server Crashed KTHXBAI")
	s:close()
end
--old shutdown hook

--string.Replace( string text, string to_be_replaced, string replace_with )
function changeTopic()
	Topic = Chan.." | "..Host.." |Players: "..Players.."| Map: "..Map
	ircSend("TOPIC "..Chan.." :"..Topic)
end

function ircParse(p)
	if string.find(p,"ERROR") then 
		ircMsg("Error report(Please Tell ahref):"..p)
		return
	end
	prefix, cmd, param = string.match(p, "^:([^ ]+) ([^ ]+)(.*)$")
	--user,cmd,channel,message = string.match(line, "^:([^ ]+)! ([^ ]+) (#[%w%]+) :([%W%w%s]+)$") this does not work and makes me cry :(
	if cmd == "PRIVMSG" then
		if prefix and string.find(prefix,"!") then
			user = string.match(prefix, "(%w*)!")
		end
		channel = string.match(param, "#[%w]+") 
		message = string.match(param, " :([%W%w%s]+)") 
		if user == "IRC" or not user then return end 
		--handle private messages
		if cmd =="PRIVMSG" then
			ircPrivMsg(user,message)
		end
		if cmd == "JOIN" then
			ircSend("WHOIS "..user.." "..user)
			return
		end
		if cmd == "PART" or cmd == "QUIT" then
			if table.HasValue( Ops, user) then
				for k, v in pairs(Ops) do
					if v == user then
						table.remove(ops,k)
						return
					end
				end
			end
		end	
	else 
		if cmd == "319" then --usermode data yay WHAT FUN
			local nick = string.match(param,"[%w] ([%w]+)")
			local modes = string.match(param, "([+%%~&@])"..Chan)
			if modes and not modes ~= "+" then 
				if not table.HasValue( ops, nick ) then
					table.insert( ops,nick )
				end
			end
		end
	end
end

function ircPlayerConnect(ply)
	local nick = ply:Nick()
	ircMsg(nick..":"..ply:EntIndex().." has connected.")
	Players = table.Count(player.GetAll())
	changeTopic()
end
--old player connect

function ircPlayerDisconnect(ply)
	local nick = ply:Nick()
	ircMsg(nick..":"..ply:EntIndex().." has disconnected.")
	Players = table.Count(player.GetAll()) - 1
	changeTopic()
end
-- old player disconnect


function ircGameMsg(u,txt,toall)
	if string.sub(txt,2,7) ~= "report" and string.sub(txt,1,1) == "!" then
			return
	end
	local nick = u:Nick()
	if  string.sub(txt,1,1) ~= "!" then
		ircSend("PRIVMSG "..Chan.." :".."<"..nick..">:"..txt)
		return
	else
		--PLACEHOLDER
	end
	
end
--Old Player Say

function ircThink()
	if not s then 
		ircStart()
		return 
	end
	local parse = s:receive('*l')
	if parse then
		if string.sub( parse, 1, 4 ) == "PING" then
			ircSend(string.gsub( parse, "PING", "PONG" ))
			return
		end
		ircParse(parse)
	end
end
--Think loop hook

function ircPrivMsg(u,txt)
	if  string.sub(txt,1,1) ~= "!" then
		if string.find(txt,"ACTION") then
			string.gsub(txt,"ACTION","")
			game.ConsoleCommand("say ".."<irc>"..u..txt.." \n")
			return
		end
		game.ConsoleCommand("say ".."<irc>".."<"..u..">"..txt.." \n")
		return
	else
	--string.gsub(oldString,"test","stickup")
		local line = string.Explode(" ",txt) or nil
		local cmd = string.gsub(table.remove(line,1),"!","") or nil
		--Show list of players
		if not cmd then return end
		if not line then return end
		if cmd == "players" then ircPlayers(u,cmd,line) return end
		if cmd == "exec" then ircExec(u,cmd,line) return end
		if cmd == "raw" then ircRaw(u,cmd,line) return end
		if cmd == "kick" then ircKick(u,cmd,line) return end
		if cmd == "ban" then ircBan(u,cmd,line) return end
		if cmd == "count" then ircCount(u,cmd,line) return end
	end
end
function ircPlayers(u,cmd,line)
	num = 0
	players_t = {}
	for k, v in pairs(player.GetAll()) do
		table.insert(players_t,v:Nick()..":"..v:EntIndex())
		num = num + 1
	end
	--	string.Implode( String seperator, Table table )
	players = string.Implode(",",players_t)
	ircMsg("Players:"..players.." Total:"..num)
	return
end

function ircExec(u,cmd,line)
	command = string.Implode(" ",line)
	game.ConsoleCommand( command.."\n" )
	ircMsg("I can't actually tell you if that did anything :D")
	return
end

function ircRaw(u,cmd,line)
	command = string.Implode(" ",line)
	ircSend(command)
	return
end

function ircKick(u,cmd,line)
	local player = player.GetByID(tonumber(line[1])) or nil
	if not count then
		ircMsg("Player Does not exist. Do !players to check.")
		return
	end
	table.remove(line,1)
	reason = string.Implode(" ",line)
	player:Kick(reason)
	return
end

function ircBan(u,cmd,line)
	count = player.GetByID(tonumber(line[1])) or nil
	if not count then
		ircMsg("Player Does not exist. Do !players to check.")
		return
	end
	table.remove(line,1)
	reason = string.Implode(" ",line)
	count:Ban(0,reason)
	return
end

function ircCount(u,cmd,line)
--Entity:EntIndex( ) works on players
	if #line < 2 and string.lower(line[1]) ~="all" then
		ircMsg("syntax: !count id type")
		return
	end
	if line[1] == "all" then
		props = ents.FindByClass("prop_physics")
		ircMsg("Server contains"..#props.." props.")
		return
	end
	count = player.GetByID(tonumber(line[1])) or nil
	search = string.lower(line[2]) or nil
	if not count then
		ircMsg("Player Does not exist. Do !players to check.")
		return
	end
	if search ~= "props" and search ~= "sents" then
		ircMsg("syntax: !count id type(props or sents)")
		return
	end
	ircMsg(count:Nick().." has "..count:GetCount( search ).." "..search..".")
	return
end

if not SinglePlayer() then 
	hook.Add( "Initialize", "ahrefbotstart", ircStart )
	hook.Add( "PlayerInitialSpawn", "ahrefircinitialspawn", ircPlayerConnect )
	hook.Add( "PlayerDisconnected", "ahrefircdisconnected", ircPlayerDisconnect )
	hook.Add( "PlayerSay", "ahrefircgamemessage", ircGameMsg )
	hook.Add("Think", "ahrefircthinkloop", ircThink)
	hook.Add( "ShutDown", "ahrefbotshutdown", ircShut )
end
--[[:jlj1!~jlj1@FDC777BF.FFB88ACD.E46257AB.IP PRIVMSG #THC :cowbot
[06:20:16] (cowbot@PSIGenix) > :ahref!~ahref@PSI-DA0C356.cable.ubr07.gill.blueyonder.co.uk PART #thc :BEEP
[06:20:21] (cowbot@PSIGenix) > :ahref!~ahref@PSI-DA0C356.cable.ubr07.gill.blueyonder.co.uk JOIN :#thc]]